1 package edu.jiangxin.apktoolbox.file.password.recovery.category.dictionary.singlethread;
2
3 import edu.jiangxin.apktoolbox.file.core.EncoderDetector;
4 import edu.jiangxin.apktoolbox.file.password.recovery.RecoveryPanel;
5 import edu.jiangxin.apktoolbox.file.password.recovery.category.ICategory;
6 import edu.jiangxin.apktoolbox.utils.Utils;
7 import org.apache.logging.log4j.LogManager;
8 import org.apache.logging.log4j.Logger;
9
10 import javax.swing.*;
11 import java.io.*;
12 import java.util.Optional;
13 import java.util.function.Function;
14 import java.util.function.Predicate;
15 import java.util.stream.Stream;
16
17 public class DictionarySingleThreadProxy implements ICategory {
18 private static final Logger logger = LogManager.getLogger(DictionarySingleThreadProxy.class.getSimpleName());
19
20 private boolean isCancelled;
21
22 private static class DictionarySingleThreadProxyHolder {
23 private static final DictionarySingleThreadProxy instance = new DictionarySingleThreadProxy();
24 }
25
26 private DictionarySingleThreadProxy() {
27 }
28
29 public static DictionarySingleThreadProxy getInstance() {
30 return DictionarySingleThreadProxy.DictionarySingleThreadProxyHolder.instance;
31 }
32
33 private String startAndGet(String charsetName, RecoveryPanel panel) {
34 isCancelled = false;
35 Predicate<String> isRecoveringPredicate = password -> (!isCancelled);
36 Function<String, Stream<String>> generator = password -> {
37 panel.setCurrentPassword(password);
38 panel.increaseProgressBarValue();
39 return Stream.of(password.toLowerCase(), password.toUpperCase());
40 };
41 Predicate<String> verifier = panel.getCurrentFileChecker()::checkPassword;
42 try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(panel.getDictionaryFile()), charsetName))) {
43
44 Optional<String> password = br.lines().takeWhile(isRecoveringPredicate).flatMap(generator).filter(verifier).findFirst();
45 return password.orElse(null);
46 } catch (FileNotFoundException e) {
47 logger.info("FileNotFoundException");
48 } catch (IOException e) {
49 logger.info("IOException");
50 }
51 return null;
52 }
53
54 @Override
55 public void start(RecoveryPanel panel) {
56 File dictionaryFile = panel.getDictionaryFile();
57 if (!dictionaryFile.isFile()) {
58 JOptionPane.showMessageDialog(panel, "Invalid dictionary file");
59 return;
60 }
61 String charsetName = EncoderDetector.judgeFile(dictionaryFile.getAbsolutePath());
62 logger.info("dictionary file: {}, charset: {}", dictionaryFile.getAbsolutePath(), charsetName);
63 if (charsetName == null) {
64 JOptionPane.showMessageDialog(panel, "Invalid charsetName");
65 return;
66 }
67 panel.resetProgressMaxValue(Utils.getFileLineCount(dictionaryFile));
68 String password = startAndGet(charsetName, panel);
69 panel.showResultWithDialog(password);
70 }
71
72 @Override
73 public void cancel() {
74 isCancelled = true;
75 }
76 }